package org.zxp.thread.volatileTest;

/**
 * @program: zxp-thread-test
 * @description: 这是 volitile 的第一种用法 有人说是线程开关 或者状态标记
 * 我总结了以个特点：只有一个线程控制改变volitile变量的值 很多线程并发读取volitile变量的值都可以用volitile
 * @author: X-Pacific zhang
 * @create: 2019-05-10 17:04
 **/
public class VolatileTest {
    public static volatile boolean flag = false;
    public static int num = 0;

    public static void main(String[] args){
        //这种情况不添加volatile就有可能造成无法退出程序了（我测试当不在while(!flag){上sleep，会一直循环，这种非常可能拿不到更改后的值，一直从工作内容中获得缓存值）
        //添加了volatile就强制从主内存中获得值，就不会出现上述问题了
        //这个例子体现：只有一个线程控制改变volitile变量的值 很多线程并发读取volitile变量的值都可以用volitile
        new Thread(() -> {
            while(!flag){
            }
            System.out.println("退出了");
        }).start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("setup");
        flag = true;
        //volatile无法解决的问题：线程安全
        //下面这个例子极容易得出num不为1000的情况，所以volatile只能保证每次获取数据从主内存中获取而并不能保证变量的操作原子性
        //原子性的问题参见javap -v反编译字节码指令
//        for (int i = 0; i < 1000; i++) {
//            new Thread(() -> {
//                num++;
//            }).start();
//        }
//        while (true){
//            System.out.println(num);
//        }
    }

}
